package com.woniuxy.rabbitmq79.consumer;

import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @Author zhangyong
 * @Date 2021/8/11 0011下午 4:00
 */
public class ConfirmConsumer {
    public static void main(String[] args) throws Exception {
        //1.创建连接工厂：创建连接
        ConnectionFactory factory = new ConnectionFactory();

        //2.设置连接参数
        factory.setHost("localhost");   //mq的ip
        factory.setUsername("guest");   //账号
        factory.setPassword("guest");   //密码
        factory.setVirtualHost("/");    //设置虚拟主机 不设置默认/

        //3.创建连接
        Connection connection = factory.newConnection();     //IO异常

        //4.创建通道
        Channel channel = connection.createChannel();

        //创建消息队列
        //参数1：队列的名字
        //参数2：是否持久化队列 ：rabbitmq停机时，将消息队列和里面的消息进行持久化
        //参数3：是否排它，是否只允许一个消费者连接
        //参数4：是否自动删除这个队列
        //参数5:初始化参数（消息队列的长度，死信交换，消息溢出处理方式等。。。）
        channel.queueDeclare("consumer", true, false, false, null);

        //设置预取值:消费者每次拿几个
        channel.basicQos(1);

        //6.创建消费者对象
        Consumer consumer = new DefaultConsumer(channel) {
            //
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                //
                String message = new String(body, "UTF-8");
                //
                //System.out.println(message);
                long deliveryTag = envelope.getDeliveryTag();
                try {
                    Thread.sleep(5000);
                    //假设业务处理没有问题，应该向消息队列发送消息消费确认
                    /**
                     * ack  消息确认
                     * 参数1：消息的tag
                     * 参数2：是否一次性确认所有消息被消费，通常写false
                     */
                    System.out.println(deliveryTag + "consumer");
                    channel.basicAck(deliveryTag, false);
                } catch (Exception e) {
                    //nack  消费者向消息队列说没收到    拒绝消息
                    /**
                     * 参数1：消息的tag
                     * 参数2：是否一次性确认所有消息被消费，通常写false
                     * 参数3：是否将信息重新放入队列，而且砸队列头，是否被重新消费
                     * 如果是true  重新放到消息队列尾，然后重新消费  false 将消息删除(死信)
                     */
                    channel.basicNack(deliveryTag, false, false);
                }
            }
        };

        //7.消费者消费消息
        //参数1：消息队列名字
        //参数2：是否确认消息已经收到
        //参数3：接收到消息之后由谁来处理
        channel.basicConsume("consumer", false, consumer);
    }
}
